/*******************************************************************************
 * Copyright (c) 2006 Ultimate Technology, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Bojan Vukojevic - initial API and implementation
 *******************************************************************************/
package com.ultimatetech.cim.views;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import javax.wbem.cim.CIMClass;
import javax.wbem.cim.CIMException;
import javax.wbem.cim.CIMMethod;
import javax.wbem.cim.CIMObjectPath;
import javax.wbem.cim.CIMProperty;
import javax.wbem.cim.CIMQualifier;
import javax.wbem.client.CIMClient;

import org.eclipse.core.runtime.Preferences;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import com.ultimatetech.cim.CIMPlugin;
import com.ultimatetech.cim.graphical.PersistentToolTipListener;
import com.ultimatetech.cim.graphical.UMLCIMClass;
import com.ultimatetech.cim.graphical.UMLCIMClassMouseListener;
import com.ultimatetech.cim.preferences.CIMPreferencePage;
import com.ultimatetech.cim.views.content.CIMConnect;

public class CIMClassHierarchyView extends ViewPart {
    Canvas canvas = null;
    CIMClass cc = null;
    CIMObjectPath cop = null;
    Composite parent = null;
    ScrollPane pane = null;
    public CIMClassHierarchyView() {
		super();		
	}

	public void createPartControl(Composite parent) {
		this.parent = parent;
		pane = new ScrollPane();		
		pane.setBackgroundColor(new Color(null, 255, 255, 255));
		pane.setScrollBarVisibility(ScrollPane.AUTOMATIC);		
		canvas = new Canvas (parent, SWT.BORDER);
		
		if(cc != null){
		 drawCIMClass();
		}
		
	} 
	
	private void drawCIMClass() {
		if(cop == null) return;
		List<UMLCIMClass> subclasses = new ArrayList<UMLCIMClass>();
		Figure mainClass;
		Preferences pref = CIMPlugin.getDefault().getPluginPreferences();
		CIMClient client = CIMConnect.connect(
				pref.getString(CIMPreferencePage.PreferenceNames.IS_SECURE),
				pref.getString(CIMPreferencePage.PreferenceNames.CIM_HOST),
				pref.getString(CIMPreferencePage.PreferenceNames.CIM_PORT),
				pref.getString(CIMPreferencePage.PreferenceNames.CIM_NAMESPACE)
				);
		List<CIMClass> subClassList = new ArrayList<CIMClass>();
		try {
			cc = client.getClass(cop, true, true, true, null);
			Enumeration<?>  children = client.enumerateClasses(cop);
			while(children != null && children.hasMoreElements()){
				subClassList.add((CIMClass) children.nextElement());
			}			
		LightweightSystem lws = new LightweightSystem(canvas);
		if(pane != null){
			pane.removeAll();
		}
		
		pane = new ScrollPane();
		pane.setScrollBarVisibility(ScrollPane.AUTOMATIC);
		pane.setVisible(true);
		
		Figure contents = new Figure();		
		XYLayout contentsLayout = new XYLayout();
		contents.setLayoutManager(contentsLayout);
		Font classFont = new Font(null, "Arial", 10, SWT.BOLD);
		ImageDescriptor id = CIMPlugin.getImageDescriptor("icons/class_obj.gif");
		int y = 10;
		int x = 10;
		int maxy = 10;
		UMLCIMClass f = null;
		for(int i = 0; i < subClassList.size(); i++){
			f = addClassFigure(contents, contentsLayout, classFont, id,
					subClassList.get(i), new Color(null, 225,225, 225), x, y);
			subclasses.add(f);
			x = x + 265;
			int y1 = 40;
			y1 += f.getAttributesCompartment().getChildren().size() * 20;
			y1 +=f.getMethodsCompartment().getChildren().size() *15;
			if(y1 > maxy){
				maxy = y1;
			}
		}
		x = x/2;
		if(maxy > 10) maxy += 50;
		y = maxy ;

		f = addClassFigure(contents, contentsLayout, classFont, id, cc, null, x, y);
		mainClass = f;		
		y += 50 + f.getAttributesCompartment().getChildren().size() * 20;
		y+=f.getMethodsCompartment().getChildren().size() *15;
		
		//add superclass
		String superclass = cc.getSuperClass();
		CIMObjectPath cop = (CIMObjectPath)cc.getObjectPath().clone();
		cop.setObjectName(superclass);
		CIMClass cimSC = client.getClass(cop, false, true, true, null);
		UMLCIMClass umlSC = addClassFigure(contents, contentsLayout, classFont, id,
				cimSC, new Color(null, 225,225, 225), x, y);
				
		addConnection(contents, (Figure)umlSC, (UMLCIMClass)mainClass, Graphics.LINE_SOLID);
		
		for(int i = 0; i < subclasses.size(); i++){
			addConnection(contents, mainClass, subclasses.get(i), Graphics.LINE_SOLID);
		}
		x = 10;
		/*for(int i = 0; i < copList.size(); i++){
			f = addClassFigure(contents, contentsLayout, classFont, id,
					(CIMClass)copList.get(i), null, x, y);
			addConnection(contents, mainClass, f, Graphics.LINE_DASH);
			x = x + 265;
			
		}*/
		pane.add(contents);
		pane.setConstraint(contents, new Rectangle(0, 0, -1, -1));
		pane.setContents(contents);
		lws.setContents(pane);
		} catch (CIMException e) {
			e.printStackTrace();
		}
	}

	private void addConnection(Figure contents, Figure mainClass, UMLCIMClass f, int lineStyle) {
		PolylineConnection c = new PolylineConnection();
		ChopboxAnchor sourceAnchor = new ChopboxAnchor(mainClass);
		ChopboxAnchor targetAnchor = new ChopboxAnchor(f);
		c.setSourceAnchor(sourceAnchor);
		c.setTargetAnchor(targetAnchor);
		c.setLineStyle(lineStyle);
		if(lineStyle == Graphics.LINE_SOLID){
		    PolygonDecoration decoration = new PolygonDecoration();
		    c.setTargetDecoration(decoration);
		}
		contents.add(c);
	}

	private UMLCIMClass addClassFigure(//ScrollPane contents,
			Figure contents,
			XYLayout contentsLayout,
			Font classFont, 
			ImageDescriptor id,
			CIMClass cc, 
			Color color,
			int x, int y) {
		Label classLabel1 = new Label(cc.getName(), id.createImage()); 				
		classLabel1.setFont(classFont);
		Vector<?> vc = cc.getQualifiers();
		StringBuffer buf = new StringBuffer("");
		makeToolTipText(vc, buf);
		if(!cc.getName().equals(this.cc.getName())){
			buf.append("\n    >> Double-click to display hierarchy <<");
		}
		//classLabel1.setToolTip(new Label(buf.toString()));
		classLabel1.addMouseMotionListener(
				new PersistentToolTipListener(
						classLabel1, buf.toString(), parent));
		classLabel1.addMouseListener(new UMLCIMClassMouseListener(cc));
		//classLabel1.setBackgroundColor(new Color(null, 88, 88, 8));
		UMLCIMClass classFigure = new UMLCIMClass(classLabel1, color, cc, parent);
		
		//XYLayout contentsLayout = new XYLayout();
		id = CIMPlugin.getImageDescriptor("icons/field_private_obj.gif");
		Vector<?> v = cc.getAllProperties();
		if(v != null){
			for(int i = 0; i < v.size();i++){
				CIMProperty cp = (CIMProperty)v.get(i);
				String pn = cp.getName();
				String type = cp.getType().toMOF();				
				Label attribute1 = new Label(pn + ": " + type, id.createImage());
				vc = cp.getQualifiers();
				buf = new StringBuffer("");
				makeToolTipText(vc, buf);
				attribute1.addMouseMotionListener(
						new PersistentToolTipListener(
								attribute1, buf.toString(), parent));
				classFigure.getAttributesCompartment().add(attribute1);
				
			}
		}
		id = CIMPlugin.getImageDescriptor("icons/methpub_obj.gif");
		v = cc.getAllMethods();
		if(v != null){
			for(int i = 0; i < v.size();i++){
				CIMMethod cm = (CIMMethod)v.get(i);
				Label method1 = new Label(cm.getName() + ": " + cm.getType().toMOF(), id.createImage());
				vc = cm.getQualifiers();
				buf = new StringBuffer("");
				makeToolTipText(vc, buf);
				method1.addMouseMotionListener(
						new PersistentToolTipListener(
								method1, buf.toString(), parent));
				classFigure.getMethodsCompartment().add(method1);
			}
		}		
		contentsLayout.setConstraint(classFigure, new Rectangle(x, y, -1, -1));		
		contents.add(classFigure);
		return classFigure;
	}

	/**
	 * @param vc
	 * @param buf
	 */
	private void makeToolTipText(Vector<?> vc, StringBuffer buf) {
		int vs = vc == null ? 0 : vc.size();
		for(int i = 0; i < vs; i ++){
			String q = ((CIMQualifier)vc.get(i)).toMOF();
			if(q.length() > 30){
				String words[] =  q.split(" ");
				StringBuffer xbuf = new StringBuffer("");
				for(int z = 0; z < words.length; z++){
					xbuf.append(words[z]).append(" ");
					if(xbuf.length() > 60){
						buf.append(xbuf).append("\n");
						xbuf = new StringBuffer("");
					} 
				}
				if(xbuf.length() != 0) {
					buf.append(xbuf).append("\n");
					xbuf = null;
				}
			} else {
				buf.append(q).append("\n");
			}
		}
		if(buf.length() == 0){
			buf.append("<No Qualifiers>");
		}
	}

	public void setFocus() {
		// TODO Auto-generated method stub

	}

	public void setCimObjectPath(CIMObjectPath cop) {		
		if(canvas != null){
			if(pane != null){
			pane.removeAll();			
			}
			this.cop = null;
			canvas.redraw();
			canvas.update();
			this.cop = cop;	
			drawCIMClass();
			canvas.redraw();
			canvas.update();
		}
		this.cop = cop;
	}
	
	public CIMObjectPath getCimObjectPath(){
		return cop;
	}

}
